<?php

namespace wanghua\general_utility_tools_php\websocket;

use app\api\logic\TyuserLogic;
use GatewayWorker\Lib\Gateway;
use IFlytek\Xfyun\Speech\LfasrClient;
use think\Db;
use think\worker\Application;
use wanghua\general_utility_tools_php\http\Curl;
use wanghua\general_utility_tools_php\tool\Tools;
use Workerman\Worker;
use think\worker\Events;


/**
 * 事件监控基类，附安装说明和是使用说明
 *
 *
 * 【安装方法】
 * 1、安装长连接框架：composer require workerman/gateway-worker
 *      （1.1）手册：http://www.workerman.net/gatewaydoc/
 *      （1.2）websocket使用MySQL：https://www.workerman.net/doc/workerman/components/workerman-mysql.html
 *
 * 2、配置基本参数
 *      配置为文件为 config/gateway_worker.php（必须使用对应命令才能启动）
 *          配置端口startPort，pingData，eventHandler，其它默认就好
 *              eventHandler配置为app\index\logic\events\Events.php类，用于处理监听后的业务逻辑
 * 3、启动服务
 *      启动命令为：php think worker:gateway
 *      守护进程启动：php think worker:gateway -d
 * 4、   nginx服务配置以支持/wss方式访问
 *      参考配置：
 *      location /wss
{
proxy_pass http://127.0.0.1:2000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header X-Real-IP $remote_addr;
}
 * 5、JavaScript客户端建立连接并访问
 *      ws = new WebSocket("wss://boomim.playone.cn/wss");//这种访问方式需要nginx配置
ws.onopen = function() {
alert("连接成功");
ws.send('hello,thinkphp');
alert("给服务端发送一个字符串：hello,thinkphp");
};
 * 【使用方法】
 * 1.在业务系统中新建一个类继承此BaseEvents类，并按需重写onClose方法（如果不需要则不重写）。
 * 2.onMessage事件的业务代码必须放在所在业务系统目录：api/logic/中，本类会将onMessage请求路由到该目录中
 *      （2.1）业务逻辑命名规则：业务名称+Logic后缀，如：TychatLogic.php（听译聊天）
 * 3.客户端请求数据格式为：
 *      {
 *          "action":"Tychat/saveChatHistory",//业务名称/接口名
 *          "items":{"chat_msg":"你好","type":"doc"}//数据包
 *      }
 *
 */
class BaseEvents extends Events
{

    private static $wssObject = null;
    /**
     * onWorkerStart 事件回调
     * 当businessWorker进程启动时触发。每个进程生命周期内都只会触发一次
     *
     * @access public
     * @param  \Workerman\Worker    $businessWorker
     * @return void
     */
    public static function onWorkerStart(Worker $businessWorker)
    {
        //一个连接只触发一次
        Tools::log_to_write_txt(['businessWorker启动（一个连接只触发一次）：'=>$businessWorker]);
        $app = new Application;

        $app->initialize();


        self::$wssObject = new BaseWebsocketLogic();
    }

    /**
     * onConnect 事件回调
     * 当客户端连接上gateway进程时(TCP三次握手完毕时)触发
     *
     * @access public
     * @param  int       $client_id
     * @return void
     */
    public static function onConnect($client_id)
    {
        //一个连接只触发一次
        Tools::log_to_write_txt(['客户端完成TCP握手：'=>"[{$client_id}]"]);

        $json = Tools::json_wss('onConnect','连接成功',['client_id'=>$client_id]);
        Gateway::sendToCurrentClient($json);
    }

    public static function onWebSocketConnect($client_id, $data)
    {

//        var_export($data);
        //对应客户端打开连接, 一个连接只触发一次
        Tools::log_to_write_txt(['客户端打开了websocket连接',$client_id,$data]);
        //$res = Tools::set_ok('ok',['client_id'=>$client_id,'msg'=>'客户端打开连接时，发送到服务端的消息：','data'=>$data]);
        //
        //Gateway::sendToCurrentClient(json_encode($res,JSON_UNESCAPED_UNICODE));
        //$json = Tools::json_wss('openConnect','打开连接成功',['client_id'=>$client_id,'data'=>$data]);
        //Gateway::sendToCurrentClient($json);
    }

    /**
     * onMessage 事件回调
     * 当客户端发来数据(Gateway进程收到数据)后触发
     *
     * 解析消息,根据action处理业务逻辑
     *
     * @access public
     * @param  int       $client_id
     * @param  mixed     $data
     * @return void
     */
    public static function onMessage($client_id, $data)
    {
        Tools::log_to_write_txt(['客户端发来数据(Gateway进程收到数据).client_id:'.$client_id,$data]);
        //$res = Tools::set_ok('ok',['client_id'=>$client_id,'msg'=>'你发来的消息我接收到了：',$client_id=>$data]);
        //Gateway::sendToClient($client_id,json_encode($res,JSON_UNESCAPED_UNICODE));

        //if(empty($data)){
        //    $json = Tools::json_wss('error','消息为空');
        //
        //    Gateway::sendToClient($client_id, $json);
        //    return ;
        //}
        ////解析消息
        //$xunfei_record_config = config('xunfei_record_config');
        //$appId = $xunfei_record_config['appid'];
        //$secretKey = $xunfei_record_config['secretKey'];
        //
        ////解析action
        //// 处理接收到的语音数据
        //// 这里需要将二进制数据转换为讯飞API所需的格式
        //// 以下代码仅为示例，具体实现需要根据讯飞API文档进行调整
        //$lfasrClient = new LfasrClient($appId, $secretKey);
        //$lfasrClient->sendBinaryData($data, function ($result) use ($client_id) {
        //    // 处理讯飞API返回的实时转写结果
        //    // 将结果发送回客户端
        //    Gateway::sendToClient($client_id, json_encode(['type' => 'transcription', 'data' => $result]));
        //});

        //初始化websocket业务逻辑路由控制对象
        //$obj = new BaseWebsocketLogic();
        //$obj->domsg($client_id,$data);
        self::$wssObject->domsg($client_id,$data);

    }

    /**
     * onClose 事件回调 当用户断开连接时触发的方法
     *
     *【重要】：继承该类时重写断开业务逻辑
     *
     * @param  integer $client_id 断开连接的客户端client_id
     * @return void
     */
    public static function onClose($client_id)
    {
        //GateWay::sendToAll("client[$client_id] logout\n");
        Tools::log_to_write_txt(['断开连接.client_id:'.$client_id]);

        //$url = 'https://boomim.playone.cn/api/Partnermerchants/offline';
        //Curl::curl_post($url,['clientid'=>$client_id]);

        //(new TyuserLogic())->offline($client_id);
        //self::$wssObject->doOffline($client_id);
    }

    /**
     * onWorkerStop 事件回调
     * 当businessWorker进程退出时触发。每个进程生命周期内都只会触发一次。
     *
     * @param  \Workerman\Worker    $businessWorker
     * @return void
     */
    public static function onWorkerStop(Worker $businessWorker)
    {
        //echo "WorkerStop\n";
        Tools::log_to_write_txt(['businessWorker进程退出时触发。每个进程生命周期内都只会触发一次.',$businessWorker]);
        //所有人离线，不需要修改所有用户离线状态，
        //因为离线后再上线clint_id会重新生成
    }
}